import { cloneDeep } from 'lodash-es';
import { useRoute } from 'vue-router';
import { views } from '@/router/elegant/imports';
import { useAuthStore } from '@/store/modules/auth';

export type Utils = {
  handleTree: (data: any, id: any, parentId?: any, children?: any) => any[];
  findNodesWithChildren: (tree: any[], childrenKey: string) => any[];
  parseTime: (time: any, pattern?: any) => any;
  isNonNegativeInteger: (str: string) => boolean;
  getAllPageRouteName: () => string[];
  deepClone: <T>(obj: T) => T;
  checkAuth: (value: string[]) => boolean;
  getRouteParams: () => string;
  tabMessageChannel: (channelName: string) => {
    postMessage: (data: any) => void;
    getMessage: () => void;
    close: () => void;
  };
};

/**
 * 构造树型结构数据
 *
 * @param {any} data 数据源
 * @param {any} id id字段 默认 'id'
 * @param {any} parentId 父节点字段 默认 'parentId'
 * @param {any} children 孩子节点字段 默认 'children'
 */

// eslint-disable-next-line max-params
export function handleTree(data: any, id: any, parentId?: any, children?: any) {
  const config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children'
  };

  const childrenListMap: any = {};
  const nodeIds: any = {};
  const tree: any = [];

  for (const d of data) {
    // eslint-disable-next-line @typescript-eslint/no-shadow
    const parentId = d[config.parentId];
    // eslint-disable-next-line no-eq-null, eqeqeq
    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = [];
    }
    nodeIds[d[config.id]] = d;
    childrenListMap[parentId].push(d);
  }

  for (const d of data) {
    // eslint-disable-next-line @typescript-eslint/no-shadow
    const parentId = d[config.parentId];
    // eslint-disable-next-line no-eq-null, eqeqeq
    if (nodeIds[parentId] == null) {
      tree.push(d);
    }
  }

  for (const t of tree) {
    adaptToChildrenList(t);
  }

  function adaptToChildrenList(o: any) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]];
    }
    if (o[config.childrenList]) {
      for (const c of o[config.childrenList]) {
        adaptToChildrenList(c);
      }
    }
  }
  return tree;
}

/**
 * 遍历树形结构并收集所有包含 children 的节点
 *
 * @param tree - 树形结构的根节点数组
 * @param childrenKey - 子节点的键名，默认为 'children'
 * @returns 包含 children 的所有节点组成的数组
 */
export function findNodesWithChildren(tree: any[], childrenKey: string = 'children'): any[] {
  const result: any[] = [];

  function traverse(nodes: any[]): void {
    nodes.forEach(node => {
      if (node[childrenKey] && Array.isArray(node[childrenKey]) && node[childrenKey].length > 0) {
        // 如果当前节点包含 children 并且 children 是非空数组，则添加到结果数组
        result.push(node);
      }
      // 继续递归遍历 children
      if (node[childrenKey]) {
        traverse(node[childrenKey]);
      }
    });
  }

  traverse(tree);
  return result;
}

// 日期格式化
export function parseTime(time: any, pattern?: any) {
  if (arguments.length === 0 || !time) {
    return null;
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}';
  let date;
  if (typeof time === 'object') {
    date = time;
  } else {
    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
      // eslint-disable-next-line no-param-reassign
      time = Number.parseInt(time, 10);
    } else if (typeof time === 'string') {
      // eslint-disable-next-line no-param-reassign
      time = time
        // eslint-disable-next-line prefer-regex-literals
        .replace(new RegExp(/-/gm), '/')
        .replace('T', ' ')
        // eslint-disable-next-line prefer-regex-literals
        .replace(new RegExp(/\.[\d]{3}/gm), '');
    }
    if (typeof time === 'number' && time.toString().length === 10) {
      // eslint-disable-next-line no-param-reassign
      time *= 1000;
    }
    date = new Date(time);
  }
  const formatObj: any = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  };
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result: any, key: any) => {
    let value = formatObj[key];
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value];
    }
    if (result.length > 0 && value < 10) {
      value = `0${value}`;
    }
    return value || 0;
  });
  return time_str;
}

export function isNonNegativeInteger(str: string) {
  // 正则表达式匹配非负整数
  const regex = /^[0-9]*[1-9][0-9]*$|^[0]$/;
  return regex.test(str);
}

export function getAllPageRouteName() {
  return Object.keys(views);
}

export function deepClone<T>(obj: T) {
  return cloneDeep(obj);
}

export function checkAuth(value: string[]): boolean {
  const authStore = useAuthStore();
  const all_permission = '*:*:*';
  const permissions = authStore.userInfo.permissions;
  if (value && Array.isArray(value) && value.length > 0) {
    const permissionFlag = value;
    const hasPermissions = permissions.some(permission => {
      return all_permission === permission || permissionFlag.includes(permission);
    });

    if (!hasPermissions) {
      return false;
    }
    return true;
  }
  return false;
}

/**
 * 获取路由末尾的参数
 *
 * @returns {string} 返回路由末尾的参数
 */
export function getRouteParams() {
  const route = useRoute();
  const fullPathArr = route.fullPath.split('/');
  const params = fullPathArr[fullPathArr.length - 1];
  if (params.includes('?')) {
    return params.split('?')[0];
  }
  return params;
}

/** 标签消息广播 */

export function tabMessageChannel(channelName: string) {
  const channel = new BroadcastChannel(channelName);

  // 发送消息
  const postMessage = (data: any) => {
    channel.postMessage(data);
  };

  // 接收消息
  const getMessage = () => {
    channel.onmessage = data => {
      console.log('接收到消息', data.data);
    };
  };

  // 关闭消息通道
  console.log('通道信息实体', channel);
  const close = () => channel.close();

  return {
    postMessage,
    getMessage,
    close
  };
}

export default {
  handleTree,
  findNodesWithChildren,
  parseTime,
  isNonNegativeInteger,
  getAllPageRouteName,
  deepClone,
  checkAuth,
  getRouteParams
};
